﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using TileMapEditor.Internal;
using TileMapEditor.Config;

namespace TileMapEditor.Core
{
    [Serializable]
    public class TileMapBrush : ScriptableObject
    {
        public enum BrushType
        {
            CIRCLE,
            SQUARE
        }

        public enum BrushApproach
        {
            MANUALLY,
            SELECT_POINT
        }

        private Vector2 _stride = Vector2.zero;
        public Vector2 stride
        {
            get { return _stride; }
            set { _stride = value; }
        }

        [SerializeField]
        private int _size = 0;
        public int size
        {
            get { return _size; }
            set { _size = value; }
        }

        private Color _brush_color;

        private int _paint_type = 0x01;
        public int paintType
        {
            get { return _paint_type; }
        }

        [SerializeField]
        private int _layer_idx = 0;
        private string _layer;
        public string layer
        {
            get { return _layer; }
            set { _layer = value; }
        }

        private BrushApproach _brush_approach;

        #region Events

        public Action<Dictionary<Vector2, int>> OnPaintCurrentRegion;

        #endregion End Events


        #region Data

        //public List<Vector2> _covered_region = new List<Vector2>();
        //public List<Vector2> coveredRegion
        //{
        //    get { return _covered_region; }
        //}

        public Dictionary<Vector2, int> _covered_region;

        #endregion End Data

        // TODO
        public void DrawCircle( int radius )
        {

        }

        public void DrawBrush( Vector2 center )
        {
            _covered_region.Clear();

            Vector2 t = center;
            for ( int i = -size; i <= size; i++ ) // x
            {
                for ( int j = -size; j <= size; j++ ) // y
                {
                    t.x = center.x + i;
                    t.y = center.y + j;

                    DrawPixel( t );
                    SetPixel( t, _paint_type );
                }
            }
        }

        public void DrawPixel( Vector2 pos )
        {
            DrawPixel( pos, _paint_type, true );
        }

        public void DrawPixel( Vector2 pos, int area_code )
        {
            DrawPixel( pos, area_code, false );
        }

        public void DrawPixel( Vector2 pos, int area_code, bool for_brush )
        {
            if ( TileMapPainter.Instance.IsMouseInner( pos ) )
            {
                var org = new Vector2() {
                    x = pos.x * _stride.x,
                    y = pos.y * _stride.y
                };

                TileMapEditorUtility.BeginQuads( TileMapSettings.GetAreaColor( area_code, for_brush) );
                TileMapEditorUtility.DrawQuads( new Rect( org.x, org.y, _stride.x + 1, _stride.y + 1 ) );
                TileMapEditorUtility.EndQuads();
            }
        }

        /// <summary>
        /// This function will set the covered region color.
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="paint_type"></param>
        public void SetPixel( Vector2 pos, int area_code )
        {
            if ( _covered_region.ContainsKey( pos ) )
            {
                _covered_region[pos] = area_code;
            }
            else
            {
                _covered_region.Add( pos, area_code );
            }
        }

        public void SetBrushStride( Vector2 new_stride )
        {
            stride = new_stride;
        }

        public void PaintCurrentRegion()
        {
            if (null != OnPaintCurrentRegion)
            {
                //Debug.LogFormat( "Covered Region Size: {0}", _covered_region.Count );
                OnPaintCurrentRegion.Invoke( _covered_region );
            }
        }

        public void ClearCoveredRegion()
        {
            _covered_region.Clear();
        }

        private void OnEnable()
        {
            _covered_region = new Dictionary<Vector2, int>();
        }

        public void OnGUI()
        {
            EditorGUILayout.BeginVertical();

            EditorGUILayout.LabelField( "Brush Settings", EditorStyles.boldLabel );

            {
                EditorGUILayout.BeginHorizontal();

                if ( GUILayout.Button( TileMapBrushStyles.earseLabel,
                    _paint_type == TileMapSettings.areaType[TileMapIds.blocked] ? TileMapBrushStyles.ToggleButtonStyleToggled : TileMapBrushStyles.ToggleButtonStyleNormal ) )
                {
                    _paint_type = TileMapSettings.areaType[TileMapIds.blocked];
                }

                if ( GUILayout.Button( TileMapBrushStyles.walkingLabel,
                    _paint_type == TileMapSettings.areaType[TileMapIds.walking] ? TileMapBrushStyles.ToggleButtonStyleToggled : TileMapBrushStyles.ToggleButtonStyleNormal ) )
                {
                    _paint_type = TileMapSettings.areaType[TileMapIds.walking];
                }

                if ( GUILayout.Button( TileMapBrushStyles.occuluedLabel,
                    _paint_type == TileMapSettings.areaType[TileMapIds.occluded] ? TileMapBrushStyles.ToggleButtonStyleToggled : TileMapBrushStyles.ToggleButtonStyleNormal ) )
                {
                    _paint_type = TileMapSettings.areaType[TileMapIds.occluded];
                }

                if ( GUILayout.Button( TileMapBrushStyles.npcLabel,
                    _paint_type == TileMapSettings.areaType[TileMapIds.npc] ? TileMapBrushStyles.ToggleButtonStyleToggled : TileMapBrushStyles.ToggleButtonStyleNormal ) )
                {
                    _paint_type = TileMapSettings.areaType[TileMapIds.npc];
                }

                EditorGUILayout.EndHorizontal();

                _brush_color = TileMapSettings.GetAreaColor( _paint_type );

                EditorGUI.BeginDisabledGroup( true );
                EditorGUILayout.ColorField( TileMapBrushStyles.brushColorLabel, _brush_color );
                EditorGUI.EndDisabledGroup();
            }

            if ( _paint_type == TileMapSettings.areaType[TileMapIds.npc] )
            {
                size = 0;
            }

            EditorGUI.BeginDisabledGroup( _paint_type == TileMapSettings.areaType[TileMapIds.npc] );
            {
                EditorGUILayout.LabelField( TileMapBrushStyles.sizeLabel );
                EditorGUILayout.BeginHorizontal();

                if ( GUILayout.Button( "0", TileMapBrushStyles.GetToggleButtonStyle( size == 0 ) ) ) { size = 0; }
                if ( GUILayout.Button( "1", TileMapBrushStyles.GetToggleButtonStyle( size == 1 ) ) ) { size = 1; }
                if ( GUILayout.Button( "2", TileMapBrushStyles.GetToggleButtonStyle( size == 2 ) ) ) { size = 2; }
                if ( GUILayout.Button( "3", TileMapBrushStyles.GetToggleButtonStyle( size == 3 ) ) ) { size = 3; }

                EditorGUILayout.EndHorizontal();
            }
            EditorGUI.EndDisabledGroup();

            EditorGUILayout.EndVertical();
        }

        public static class TileMapBrushStyles
        {
            public static GUIContent sizeLabel = new GUIContent( "Brush Size" );
            public static GUIContent brushColorLabel = new GUIContent( "Brush Color" );
            public static GUIContent approachLabel = new GUIContent( "Paint Type" );

            public static GUIContent earseLabel = new GUIContent( "Earse" );
            public static GUIContent walkingLabel = new GUIContent( "Walking" );
            public static GUIContent occuluedLabel = new GUIContent( "Occluded" );
            public static GUIContent npcLabel = new GUIContent( "NPC" );

            public static GUIStyle ToggleButtonStyleNormal = null;
            public static GUIStyle ToggleButtonStyleToggled = null;

            static TileMapBrushStyles()
            {
                if ( ToggleButtonStyleNormal == null )
                {
                    ToggleButtonStyleNormal = "Button";
                    ToggleButtonStyleToggled = new GUIStyle( ToggleButtonStyleNormal );
                    ToggleButtonStyleToggled.normal.background = Texture2D.blackTexture;
                    ToggleButtonStyleToggled.normal.textColor = Color.cyan;
                }
            }

            public static GUIStyle GetToggleButtonStyle( bool toggled )
            {
                return toggled ? ToggleButtonStyleToggled : ToggleButtonStyleNormal;
            }
        }

    }
}
